package api

import (
	"bytes"
	"shqsoft.cn/pasnj/bi/query"

	"github.com/tealeg/xlsx"
)

//Xlsx excel导出类
type Xlsx struct {
	res *query.Response
}

//NewXlsx 新建excel导出类
func NewXlsx(res *query.Response) *Xlsx {
	return &Xlsx{
		res: res,
	}
}

//Export 导出Xlsx数据
func (x *Xlsx) Export() (*bytes.Buffer, error) {
	var err error
	var sheet *xlsx.Sheet
	file := xlsx.NewFile()
	sheet, err = file.AddSheet("Sheet1")
	if err != nil {
		return nil, err
	}
	x.exportColumns(sheet)
	x.exportBody(sheet)
	buff := new(bytes.Buffer)
	file.Write(buff)
	return buff, nil
}
func (x *Xlsx) exportColumns(sheet *xlsx.Sheet) {
	maxDeep := 0
	for _, col := range x.res.Columns {
		deep := x.getColumnDeep(&col)
		if deep > maxDeep {
			maxDeep = deep
		}
	}
	for i := 0; i < maxDeep; i++ {
		sheet.AddRow()
	}
	for _, col := range x.res.Columns {
		x.exportColumn(sheet, &col, 1, maxDeep)
	}
}
func (x *Xlsx) exportColumn(sheet *xlsx.Sheet, column *query.Column, level, maxDeep int) {
	row := sheet.Rows[level-1]
	for _, col := range x.res.Columns {
		cell := row.AddCell()
		style := xlsx.Style{
			Border: *xlsx.NewBorder("thin", "thin", "thin", "thin"),
			Font:   *xlsx.NewFont(12, "宋体"),
		}
		style.Alignment.Horizontal = "center"
		style.Alignment.Vertical = "center"
		style.Font.Bold = false
		rowSpan := x.getColumnCount(&col)
		colSpan := 1
		cols := column.Children
		hasChildren := true
		if cols == nil || len(cols) == 0 {
			colSpan = maxDeep - level
			hasChildren = false
		}
		cell.Merge(rowSpan, colSpan)
		cell.SetValue(col.Title)
		cell.SetStyle(&style)
		if hasChildren {
			level++
			for _, ccol := range cols {
				x.exportColumn(sheet, &ccol, level, maxDeep)
			}
		}
	}
}
func (x *Xlsx) getColumnleafs(column *query.Column) []query.Column {
	leafs := make([]query.Column, 0)
	cols := column.Children
	if cols == nil || len(cols) == 0 {
		leafs = append(leafs, *column)
	}
	for _, ccol := range cols {
		l2 := x.getColumnleafs(&ccol)
		leafs = append(leafs, l2...)
	}
	return leafs
}

func (x *Xlsx) getColumnCount(column *query.Column) int {
	count := 0
	cols := column.Children
	if cols == nil || len(cols) == 0 {
		return 1
	}
	for _, ccol := range cols {
		c2 := x.getColumnCount(&ccol)
		count += c2
	}
	return count
}
func (x *Xlsx) getColumnDeep(column *query.Column) int {
	cols := column.Children
	if cols == nil || len(cols) == 0 {
		return 1
	}
	deep := 0
	for _, col := range cols {
		d2 := x.getColumnDeep(&col)
		if d2 > deep {
			deep = d2
		}
	}
	return deep
}
func (x *Xlsx) exportBody(sheet *xlsx.Sheet) {
	leafs := make([]query.Column, 0, 20)
	for _, col := range x.res.Columns {
		lfs := x.getColumnleafs(&col)
		leafs = append(leafs, lfs...)
	}
	for _, rowData := range x.res.DataList {
		row := sheet.AddRow()
		for _, col := range leafs {
			cell := row.AddCell()
			style := xlsx.Style{
				Border: *xlsx.NewBorder("thin", "thin", "thin", "thin"),
				Font:   *xlsx.NewFont(12, "宋体"),
			}
			style.Alignment.Horizontal = "left"
			style.Alignment.Vertical = "center"
			style.Font.Bold = false
			cell.SetValue(rowData[col.Key])
		}
	}
}
